﻿using System;
using System.Collections.Generic;
using System.Linq;
using DebIt.Persistence;
using DebIt.Persistence.Model;

namespace DebIt.Business
{
    public class DebitBusinessComponent : IDisposable
    {

        #region  variables

        private DebitDataContext _context;

        #endregion


        #region  constructors

        public DebitBusinessComponent(string connectionString)
        {
            _context = new DebitDataContext(connectionString);
            InitializeDb();
        }

        ~DebitBusinessComponent()
        {
            Dispose(false);
        }


        #endregion


        #region methods

        #region Clients

        public int Add(ClientPo client)
        {
            _context.Clients.InsertOnSubmit(client);
            _context.SubmitChanges();
            return client.ClientId;
        }

        public ClientPo GetClient(int id)
        {
            return _context.Clients.Where(x => x.ClientId == id).FirstOrDefault();
        }

        public List<ClientPo> GetAllClients()
        {
            return _context.Clients.ToList();
        }

        public void Update(ClientPo client)
        {
            var clientSto = GetClient(client.ClientId);
            clientSto.EMailAddress = client.EMailAddress;
            clientSto.FirstName = client.FirstName;
            clientSto.LastName = client.LastName;
            clientSto.Phonenumber = client.Phonenumber;
            _context.SubmitChanges();
        }

        public void DeleteClient(int id)
        {
            var clientToDelete = GetClient(id);
            if (clientToDelete == null)
                return;
            _context.Clients.DeleteOnSubmit(clientToDelete);
            _context.SubmitChanges();
        }

        #endregion


        #region Loan

        public int Add(LoanPo loan)
        {
            _context.Loans.InsertOnSubmit(loan);
            _context.SubmitChanges();
            return loan.LoanId;
        }

        public LoanPo GetLoan(int id)
        {
            return _context.Loans.Where(x => x.LoanId == id).FirstOrDefault();
        }

        public List<LoanPo> GetAllLoans()
        {
            return _context.Loans.ToList();
        }

        public void Update(LoanPo loan)
        {
            var loanSto = GetLoan(loan.LoanId);
            loanSto.Name = loan.Name;
            loanSto.Currency = loan.Currency;
            loanSto.Description = loan.Description;
            loanSto.Timestamp = loan.Timestamp;
            _context.SubmitChanges();
        }

        public void DeleteLoan(int id)
        {
            var loanToDelete = GetLoan(id);
            if (loanToDelete == null)
                return;
            _context.Loans.DeleteOnSubmit(loanToDelete);
            _context.SubmitChanges();

        }

        #endregion


        #region LoanItem

        public int Add(LoanItemPo loanItem)
        {
            loanItem.Loan = GetLoan(loanItem.Loan.LoanId);
            _context.LoanItems.InsertOnSubmit(loanItem);
            _context.SubmitChanges();
            return loanItem.LoanItemId;
        }

        public LoanItemPo GetLoanItem(int id)
        {
            return _context.LoanItems.Where(x => x.LoanItemId == id).FirstOrDefault();
        }

        public List<LoanItemPo> GetAllLoanItems()
        {
            return _context.LoanItems.ToList();
        }

        public void Update(LoanItemPo loanItem)
        {
            var loanItemSto = GetLoanItem(loanItem.LoanItemId);
            loanItemSto.Description = loanItem.Description;
            loanItemSto.Loan = GetLoan(loanItem.Loan.LoanId);
            loanItemSto.Value = loanItem.Value;
            _context.SubmitChanges();
        }

        public void DeleteLoanItem(int id)
        {
            var loanItemToDelete = GetLoanItem(id);
            if (loanItemToDelete == null)
                return;
            _context.LoanItems.DeleteOnSubmit(loanItemToDelete);
            _context.SubmitChanges();
        }

        #endregion


        #region ClientLoanState

        public int Add(ClientLoanStatePo clientLoanState)
        {
            clientLoanState.Loan = GetLoan(clientLoanState.Loan.LoanId);
            clientLoanState.Client = GetClient(clientLoanState.Client.ClientId);
            _context.LoanClients.InsertOnSubmit(clientLoanState);
            _context.SubmitChanges();
            return clientLoanState.ClientLoanStateId;
        }

        public ClientLoanStatePo GetClientLoanState(int id)
        {
            return _context.LoanClients.Where(x => x.ClientLoanStateId == id).FirstOrDefault();
        }

        public List<ClientLoanStatePo> GetAllLoanClientStates()
        {
            return _context.LoanClients.ToList();
        }

        public void Update(ClientLoanStatePo clientLoanState)
        {
            var clientLoanStateSto = GetClientLoanState(clientLoanState.ClientLoanStateId);
            clientLoanStateSto.Client = GetClient(clientLoanState.Client.ClientId);
            clientLoanStateSto.IsPaid = clientLoanState.IsPaid;
            clientLoanStateSto.Loan = GetLoan(clientLoanState.Loan.LoanId);
            clientLoanStateSto.TimestampPaid = clientLoanState.TimestampPaid;
            _context.SubmitChanges();
        }

        public void DeleteClientLoanState(int id)
        {
            var clientLoanStateToDelete = GetClientLoanState(id);
            if (clientLoanStateToDelete == null)
                return;
            _context.LoanClients.DeleteOnSubmit(clientLoanStateToDelete);
            _context.SubmitChanges();
        }

        #endregion


        private void InitializeDb()
        {
            if (!_context.DatabaseExists())
            {
                _context.CreateDatabase();
                _context.SubmitChanges();
            }
        }

        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }

        protected virtual void Dispose(bool disposing)
        {
            if (_context == null) return;
            _context.Dispose();
            _context = null;
        }

        #endregion
    }
}
